package com.song.demo.webmvc.core;

import com.song.demo.webmvc.beans.GPBeanDefinition;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

//对配置文件进行查找、读取，解析

/**
 * 根据约定
 * BeanDefinitionReader主要完成对application.properties 配置文件的解析工作
 * 实现逻辑非常简单 通过构造函数获取从applicationContext传过来的locations配置文件的路径
 * 然后解析，扫描并保存所有相关的类并提供统一的访问入口
 */
@Data
public class GPBeanDefinitionReader {

    private List<String> registerBeanClasses = new ArrayList<String>();

    private Properties config = new Properties();
    //固定配置文件中的key,相对于xml的规范
    private  final  String SCAN_PACKAGE = "scanPackage";

    public GPBeanDefinitionReader(String ...locations){
        //通过URL定位找到其所对应的文件，然后转换成文件流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:", ""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (is !=null){
                try{
                    is.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        String property = config.getProperty(SCAN_PACKAGE);
        doScanner(property);


    }

    /**
     * 扫描路径，需要加载哪些bean
     * @param scanPackage
     */
    private void doScanner(String scanPackage) {
        String s = scanPackage.replaceAll("\\.", "/");
        URL url = this.getClass().getClassLoader().getResource(s);
        File classDir = new File(url.getFile());
        String pathParent = classDir.getPath();
        for (File file : classDir.listFiles()){

            if (file.isDirectory()){
                doScanner(scanPackage + "." + file.getName());
            }else{
                if (!file.getName().endsWith(".class")){
                    continue;
                }
                String clazzName = (scanPackage + "." +file.getName().replace(".class",""));
                registerBeanClasses.add(clazzName);
            }

        }
    }

    //把配置文件中扫描到的所有配置信息转化为beanDefinition对象，以便于之后的ioc操作
    public List<GPBeanDefinition> loadBeanDefinitions() {
        ArrayList<GPBeanDefinition> result = new ArrayList<>();
        try{
        for (String className : registerBeanClasses) {
            Class<?> beanClass = Class.forName(className);
            //如果是接口
            if (beanClass.isInterface()){
                continue;
            }
            GPBeanDefinition gpBeanDefinition = doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName());
            result.add(gpBeanDefinition);
        }} catch (Exception e){
            e.printStackTrace();
        }
        return  result;
    }

    //把每一个配置信息解析成一个BeanDefinition
    private GPBeanDefinition doCreateBeanDefinition(String factoryBeanName,String beanClassName) {
        GPBeanDefinition gpBeanDefinition = new GPBeanDefinition();
        gpBeanDefinition.setBeanClassName(beanClassName);
        gpBeanDefinition.setFactoryBeanName(factoryBeanName);
        return gpBeanDefinition;

    }

    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        //大小写字母的ASCII码相差32
        chars[0] +=32;
        return String.valueOf(chars);
    }
}
